package cn.cdutetc.library.service.impl;

import cn.cdutetc.library.entity.pojo.User;
import cn.hutool.core.bean.BeanUtil;
import cn.cdutetc.library.entity.dto.PaymentDTO;
import cn.cdutetc.library.entity.dto.PaymentStatisticsVO;
import cn.cdutetc.library.entity.dto.PaymentVO;
import cn.cdutetc.library.entity.pojo.Borrow;
import cn.cdutetc.library.entity.pojo.Payment;
import cn.cdutetc.library.entity.pojo.FeeRecord;
import cn.cdutetc.library.common.exception.BizException;
import cn.cdutetc.library.mapper.BorrowMapper;
import cn.cdutetc.library.mapper.PaymentMapper;
import cn.cdutetc.library.mapper.FeeRecordMapper;
import cn.cdutetc.library.mapper.UserMapper;
import cn.cdutetc.library.service.PaymentService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 支付服务实现类
 */
@Service
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, Payment> implements PaymentService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BorrowMapper borrowMapper;

    @Autowired
    private FeeRecordMapper feeRecordMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createPayment(PaymentDTO paymentDTO) {
        // 检查用户是否存在
        User user = userMapper.selectById(paymentDTO.getUserId());
        if (user == null) {
            throw new BizException("用户不存在");
        }

        // 从 fee_record 聚合金额
        if (paymentDTO.getRecordId() != null) {
            LambdaQueryWrapper<FeeRecord> qw = new LambdaQueryWrapper<>();
            qw.eq(FeeRecord::getRecordId, paymentDTO.getRecordId())
                    .eq(FeeRecord::getUserId, paymentDTO.getUserId())
                    .eq(FeeRecord::getStatus, "unpaid");
            List<FeeRecord> list = feeRecordMapper.selectList(qw);
            if (list == null || list.isEmpty()) {
                throw new BizException("没有需要支付的费用");
            }
            BigDecimal sum = list.stream()
                    .map(fr -> fr.getAmount() == null ? BigDecimal.ZERO : fr.getAmount())
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            paymentDTO.setAmount(sum);
        }

        // 创建支付记录
        Payment payment = new Payment();
        BeanUtil.copyProperties(paymentDTO, payment);
        payment.setStatus("unpaid");
        payment.setCreateTime(LocalDateTime.now());
        payment.setUpdateTime(LocalDateTime.now());

        this.save(payment);
        return payment.getPaymentId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completePayment(Integer paymentId, String payMethod) {
        // 检查支付记录是否存在
        Payment payment = this.getById(paymentId);
        if (payment == null) {
            throw new BizException("支付记录不存在");
        }

        // 检查支付状态
        if ("paid".equals(payment.getStatus())) {
            throw new BizException("支付已完成");
        }
        if ("refunded".equals(payment.getStatus())) {
            throw new BizException("支付已取消");
        }

        // 更新支付记录
        payment.setStatus("paid");
        payment.setPaymentType(payMethod); // 记录支付方式
        payment.setPaymentTime(LocalDateTime.now());
        payment.setUpdateTime(LocalDateTime.now());
        this.updateById(payment);

        // 联动 fee_record 置为已支付
        if (payment.getRecordId() != null) {
            LambdaQueryWrapper<FeeRecord> qw = new LambdaQueryWrapper<>();
            qw.eq(FeeRecord::getRecordId, payment.getRecordId())
                    .eq(FeeRecord::getUserId, payment.getUserId())
                    .eq(FeeRecord::getStatus, "unpaid");
            List<FeeRecord> feeRecords = feeRecordMapper.selectList(qw);
            for (FeeRecord fr : feeRecords) {
                fr.setStatus("paid");
                fr.setPayTime(LocalDateTime.now());
                feeRecordMapper.updateById(fr);
            }
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelPayment(Integer paymentId) {
        // 检查支付记录是否存在
        Payment payment = this.getById(paymentId);
        if (payment == null) {
            throw new BizException("支付记录不存在");
        }

        // 检查支付状态
        if ("paid".equals(payment.getStatus())) {
            throw new BizException("支付已完成，无法取消");
        }
        if ("refunded".equals(payment.getStatus())) {
            throw new BizException("支付已取消");
        }

        // 更新支付记录
        payment.setStatus("refunded");
        payment.setUpdateTime(LocalDateTime.now());
        return this.updateById(payment);
    }

    @Override
    public PaymentVO getPaymentById(Integer paymentId) {
        // 查询支付记录
        Payment payment = this.getById(paymentId);
        if (payment == null) {
            throw new BizException("支付记录不存在");
        }

        // 转换为VO
        return convertToVO(payment);
    }

    @Override
    public IPage<PaymentVO> pagePayments(Integer page, Integer size, String keyword, String feeType, String status) {
        // 构建查询条件
        LambdaQueryWrapper<Payment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(
                Payment::getPaymentId,
                Payment::getUserId,
                Payment::getRecordId,
                Payment::getFeeId,
                Payment::getPaymentType,
                Payment::getAmount,
                Payment::getStatus,
                Payment::getPaymentTime,
                Payment::getCreateTime,
                Payment::getUpdateTime
        );

        // 关键词搜索（搜索用户ID或用户名）
        if (keyword != null && !keyword.isEmpty()) {
            try {
                Integer userId = Integer.parseInt(keyword);
                queryWrapper.eq(Payment::getUserId, userId);
            } catch (NumberFormatException e) {
                // 如果不是数字，查询用户名（需要子查询）
                LambdaQueryWrapper<User> userQuery = new LambdaQueryWrapper<>();
                userQuery.like(User::getUsername, keyword)
                        .or()
                        .like(User::getRealName, keyword);
                List<User> users = userMapper.selectList(userQuery);
                if (users.isEmpty()) {
                    return new Page<>();
                }
                queryWrapper.in(Payment::getUserId, users.stream()
                        .map(User::getUserId)
                        .collect(Collectors.toList()));
            }
        }

        // 根据费用类型筛选（关联fee_record表）
        if (feeType != null && !feeType.isEmpty()) {
            // 先查询符合条件的fee_id
            LambdaQueryWrapper<FeeRecord> feeQuery = new LambdaQueryWrapper<>();
            feeQuery.eq(FeeRecord::getFeeType, feeType);
            List<FeeRecord> feeRecords = feeRecordMapper.selectList(feeQuery);

            if (feeRecords.isEmpty()) {
                return new Page<>();
            }

            List<Integer> feeIds = feeRecords.stream()
                    .map(FeeRecord::getFeeId)
                    .collect(Collectors.toList());

            queryWrapper.in(Payment::getFeeId, feeIds);
        }

        if (status != null && !status.isEmpty()) {
            queryWrapper.eq(Payment::getStatus, status);
        }

        queryWrapper.orderByDesc(Payment::getCreateTime);

        // 分页查询
        Page<Payment> paymentPage = new Page<>(page, size);
        Page<Payment> resultPage = this.page(paymentPage, queryWrapper);

        // 转换为VO
        List<PaymentVO> paymentVOList = resultPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        // 构建返回结果
        Page<PaymentVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(paymentVOList);

        return voPage;
    }

    @Override
    public Double getUserPaymentTotal(Integer userId) {
        // 查询用户已支付的记录
        LambdaQueryWrapper<Payment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Payment::getAmount)
                .eq(Payment::getUserId, userId)
                .eq(Payment::getStatus, "paid");
        List<Payment> payments = this.list(queryWrapper);

        // 计算总金额
        return payments.stream()
                .map(p -> p.getAmount() == null ? BigDecimal.ZERO : p.getAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .doubleValue();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handleBorrowFinePayment(Integer recordId, String payMethod) {
        // 检查借阅记录是否存在
        Borrow borrow = borrowMapper.selectById(recordId);
        if (borrow == null) {
            throw new BizException("借阅记录不存在");
        }

        // 从 fee_record 校验是否有未支付费用
        LambdaQueryWrapper<FeeRecord> qw = new LambdaQueryWrapper<>();
        qw.eq(FeeRecord::getRecordId, recordId)
                .eq(FeeRecord::getUserId, borrow.getUserId())
                .eq(FeeRecord::getStatus, "unpaid");
        List<FeeRecord> list = feeRecordMapper.selectList(qw);
        if (list == null || list.isEmpty()) {
            throw new BizException("该借阅记录没有未支付费用");
        }

        // 创建支付记录
        Payment payment = new Payment();
        payment.setUserId(borrow.getUserId());
        payment.setRecordId(recordId);
        payment.setPaymentType(payMethod);
        BigDecimal amount = list.stream()
                .map(fr -> fr.getAmount() == null ? BigDecimal.ZERO : fr.getAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        payment.setAmount(amount);
        payment.setStatus("paid");
        payment.setPaymentTime(LocalDateTime.now());
        payment.setCreateTime(LocalDateTime.now());
        payment.setUpdateTime(LocalDateTime.now());
        this.save(payment);

        // 将关联的未支付费用记录置为已支付
        LambdaQueryWrapper<FeeRecord> qw2 = new LambdaQueryWrapper<>();
        qw2.eq(FeeRecord::getRecordId, recordId)
                .eq(FeeRecord::getUserId, borrow.getUserId())
                .eq(FeeRecord::getStatus, "unpaid");
        List<FeeRecord> feeRecords = feeRecordMapper.selectList(qw2);
        for (FeeRecord fr : feeRecords) {
            fr.setStatus("paid");
            fr.setPayTime(LocalDateTime.now());
            feeRecordMapper.updateById(fr);
        }

        return true;
    }

    @Override
    public PaymentStatisticsVO getPaymentStatistics() {
        PaymentStatisticsVO statistics = new PaymentStatisticsVO();

        // 从fee_record表计算待缴金额总计
        LambdaQueryWrapper<FeeRecord> unpaidFeeWrapper = new LambdaQueryWrapper<>();
        unpaidFeeWrapper.eq(FeeRecord::getStatus, "unpaid");
        List<FeeRecord> unpaidFees = feeRecordMapper.selectList(unpaidFeeWrapper);
        BigDecimal pendingAmount = unpaidFees.stream()
                .map(fr -> fr.getAmount() == null ? BigDecimal.ZERO : fr.getAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setPendingAmount(pendingAmount.doubleValue());

        // 从fee_record表计算已缴金额总计
        LambdaQueryWrapper<FeeRecord> paidFeeWrapper = new LambdaQueryWrapper<>();
        paidFeeWrapper.eq(FeeRecord::getStatus, "paid");
        List<FeeRecord> paidFees = feeRecordMapper.selectList(paidFeeWrapper);
        BigDecimal paidAmount = paidFees.stream()
                .map(fr -> fr.getAmount() == null ? BigDecimal.ZERO : fr.getAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setPaidAmount(paidAmount.doubleValue());

        // 计算各类型费用数量（包括所有状态）
        LambdaQueryWrapper<FeeRecord> overdueWrapper = new LambdaQueryWrapper<>();
        overdueWrapper.eq(FeeRecord::getFeeType, "overdue_fee");
        statistics.setOverdueCount(feeRecordMapper.selectCount(overdueWrapper));

        LambdaQueryWrapper<FeeRecord> damageWrapper = new LambdaQueryWrapper<>();
        damageWrapper.eq(FeeRecord::getFeeType, "damage_fee");
        statistics.setDamageCount(feeRecordMapper.selectCount(damageWrapper));

        LambdaQueryWrapper<FeeRecord> lostWrapper = new LambdaQueryWrapper<>();
        lostWrapper.eq(FeeRecord::getFeeType, "loss_fee");
        statistics.setLostCount(feeRecordMapper.selectCount(lostWrapper));

        return statistics;
    }

    /**
     * 将Payment实体转换为PaymentVO
     * @param payment 支付实体
     * @return 支付VO
     */
    private PaymentVO convertToVO(Payment payment) {
        if (payment == null) {
            return null;
        }
        PaymentVO paymentVO = new PaymentVO();
        BeanUtil.copyProperties(payment, paymentVO);

        // 查询用户信息
        User user = userMapper.selectById(payment.getUserId());
        if (user != null) {
            paymentVO.setUsername(user.getUsername());
            paymentVO.setRealName(user.getRealName());
        }

        // 设置支付方式/类型描述
        String pt = payment.getPaymentType();
        if (pt != null) {
            switch (pt.toLowerCase()) {
                case "alipay": paymentVO.setPaymentTypeDesc("支付宝"); break;
                case "wechat": paymentVO.setPaymentTypeDesc("微信"); break;
                case "cash": paymentVO.setPaymentTypeDesc("现金"); break;
                default: paymentVO.setPaymentTypeDesc(pt);
            }
        }

        // 设置状态描述
        String st = payment.getStatus();
        if (st != null) {
            switch (st.toLowerCase()) {
                case "unpaid": paymentVO.setStatusDesc("待支付"); break;
                case "paid": paymentVO.setStatusDesc("已支付"); break;
                case "refunded": paymentVO.setStatusDesc("已取消"); break;
                default: paymentVO.setStatusDesc(st);
            }
        }

        // 从fee_record获取feeType
        if (payment.getFeeId() != null) {
            FeeRecord feeRecord = feeRecordMapper.selectById(payment.getFeeId());
            if (feeRecord != null) {
                paymentVO.setFeeType(feeRecord.getFeeType());
                paymentVO.setFeeRecord(feeRecord);
            }
        }

        return paymentVO;
    }

    @Override
    public IPage<PaymentVO> getUserPayments(Integer userId, Integer page, Integer size, String feeType, String status) {
        // 构建查询条件
        LambdaQueryWrapper<Payment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(
                Payment::getPaymentId,
                Payment::getUserId,
                Payment::getRecordId,
                Payment::getFeeId,
                Payment::getPaymentType,
                Payment::getAmount,
                Payment::getStatus,
                Payment::getPaymentTime,
                Payment::getCreateTime,
                Payment::getUpdateTime
        );

        // 限制为指定用户
        queryWrapper.eq(Payment::getUserId, userId);

        // 根据费用类型筛选（关联fee_record表）
        if (feeType != null && !feeType.isEmpty()) {
            // 先查询符合条件的fee_id
            LambdaQueryWrapper<FeeRecord> feeQuery = new LambdaQueryWrapper<>();
            feeQuery.eq(FeeRecord::getFeeType, feeType)
                    .eq(FeeRecord::getUserId, userId);
            List<FeeRecord> feeRecords = feeRecordMapper.selectList(feeQuery);

            if (feeRecords.isEmpty()) {
                return new Page<>();
            }

            List<Integer> feeIds = feeRecords.stream()
                    .map(FeeRecord::getFeeId)
                    .collect(Collectors.toList());

            queryWrapper.in(Payment::getFeeId, feeIds);
        }

        if (status != null && !status.isEmpty()) {
            queryWrapper.eq(Payment::getStatus, status);
        }

        queryWrapper.orderByDesc(Payment::getCreateTime);

        // 分页查询
        Page<Payment> paymentPage = new Page<>(page, size);
        Page<Payment> resultPage = this.page(paymentPage, queryWrapper);

        // 转换为VO
        List<PaymentVO> paymentVOList = resultPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        // 构建返回结果
        Page<PaymentVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(paymentVOList);

        return voPage;
    }

    @Override
    public PaymentStatisticsVO getUserPaymentStatistics(Integer userId) {
        PaymentStatisticsVO statistics = new PaymentStatisticsVO();

        // 从fee_record表计算用户待缴金额总计
        LambdaQueryWrapper<FeeRecord> unpaidFeeWrapper = new LambdaQueryWrapper<>();
        unpaidFeeWrapper.eq(FeeRecord::getStatus, "unpaid")
                .eq(FeeRecord::getUserId, userId);
        List<FeeRecord> unpaidFees = feeRecordMapper.selectList(unpaidFeeWrapper);
        BigDecimal pendingAmount = unpaidFees.stream()
                .map(fr -> fr.getAmount() == null ? BigDecimal.ZERO : fr.getAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setPendingAmount(pendingAmount.doubleValue());

        // 从fee_record表计算用户已缴金额总计
        LambdaQueryWrapper<FeeRecord> paidFeeWrapper = new LambdaQueryWrapper<>();
        paidFeeWrapper.eq(FeeRecord::getStatus, "paid")
                .eq(FeeRecord::getUserId, userId);
        List<FeeRecord> paidFees = feeRecordMapper.selectList(paidFeeWrapper);
        BigDecimal paidAmount = paidFees.stream()
                .map(fr -> fr.getAmount() == null ? BigDecimal.ZERO : fr.getAmount())
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        statistics.setPaidAmount(paidAmount.doubleValue());

        // 计算用户各类型费用数量（包括所有状态）
        LambdaQueryWrapper<FeeRecord> overdueWrapper = new LambdaQueryWrapper<>();
        overdueWrapper.eq(FeeRecord::getFeeType, "overdue_fee")
                .eq(FeeRecord::getUserId, userId);
        statistics.setOverdueCount(feeRecordMapper.selectCount(overdueWrapper));

        LambdaQueryWrapper<FeeRecord> damageWrapper = new LambdaQueryWrapper<>();
        damageWrapper.eq(FeeRecord::getFeeType, "damage_fee")
                .eq(FeeRecord::getUserId, userId);
        statistics.setDamageCount(feeRecordMapper.selectCount(damageWrapper));

        LambdaQueryWrapper<FeeRecord> lostWrapper = new LambdaQueryWrapper<>();
        lostWrapper.eq(FeeRecord::getFeeType, "loss_fee")
                .eq(FeeRecord::getUserId, userId);
        statistics.setLostCount(feeRecordMapper.selectCount(lostWrapper));

        return statistics;
    }
}
